using System;
using System.Threading;

namespace Catastrophe.Common.ThreadLock
{
	internal sealed class AsyncCoordinator
	{
		private int m_opCount = 1;

		private int m_statusReported = 0;

		private Action<CoordinationStatus> m_callback;

		private Timer m_timer;

		public void AboutToBegin(int opsToAdd = 1)
		{
			Interlocked.Add(ref this.m_opCount, opsToAdd);
		}

		public void JustEnded()
		{
			if (Interlocked.Decrement(ref this.m_opCount) == 0)
			{
				this.ReportStatus(CoordinationStatus.AllDone);
			}
		}

		public void AllBegun(Action<CoordinationStatus> callback, int timeout = -1)
		{
			this.m_callback = callback;
			if (timeout != -1)
			{
				this.m_timer = new Timer(new TimerCallback(TimeExpired), null, timeout, -1);
			}
			this.JustEnded();
		}

		private void TimeExpired(object o)
		{
			this.ReportStatus(CoordinationStatus.Timeout);
		}

		public void Cancel()
		{
			this.ReportStatus(CoordinationStatus.Cancel);
		}

		private void ReportStatus(CoordinationStatus status)
		{
			if (Interlocked.Exchange(ref this.m_statusReported, 1) == 0)
			{
				this.m_callback(status);
			}
		}

		public static int Maxinum(ref int target, Func<int, int> change)
		{
			int num = target;
			int num2;
			int num3;
			do
			{
				num2 = num;
				num3 = change(num2);
				num = Interlocked.CompareExchange(ref target, num3, num2);
			}
			while (num2 != num);
			return num3;
		}
	}
}
